package com.key.win.system.ctrl;

import com.key.win.base.auth.AuthenticationUtil;
import com.key.win.base.auth.detail.Authentication;
import com.key.win.base.web.PageRequest;
import com.key.win.base.web.PageResult;
import com.key.win.base.web.Result;
import com.key.win.common.log.annotation.LogAnnotation;
import com.key.win.common.websocket.manager.WebSocketManager;
import com.key.win.common.websocket.utils.BroadcastMessageUtil;
import com.key.win.system.model.SysDevice;
import com.key.win.system.model.SysOrgan;
import com.key.win.system.service.SysDeviceService;
import com.key.win.system.service.SysOrganService;
import com.key.win.system.service.SysUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/device/*")
@Api("Device相关的api")
public class SysDeviceCtrl {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private SysDeviceService sysDeviceService;

    @Autowired
    private WebSocketManager webSocketManager;

    @Autowired
    private SysUserService userService;

    @Autowired
    private SysOrganService sysOrganService;

    @PostMapping("/findSysDeviceByPaged")
    @ApiOperation(value = "Device分页")
    @LogAnnotation(module = "system", recordRequestParam = false)
    public PageResult<SysDevice> findSysDeviceByPaged(@RequestBody PageRequest<SysDevice> pageRequest) {
        return sysDeviceService.findSysDeviceByPaged(pageRequest);
    }

    @GetMapping("/get/{id}")
    @ApiOperation(value = "获取Device")
    @LogAnnotation(module = "system", recordRequestParam = false)
    public Result get(@PathVariable String id) {
        return Result.succeed(sysDeviceService.getById(id));
    }

    @DeleteMapping("/delete/{id}")
    @ApiOperation(value = "删除")
    @LogAnnotation(module = "system", recordRequestParam = true)
    public Result delete(@PathVariable String id) {
        boolean b = sysDeviceService.deleteById(id);
        return Result.result(b);
    }

    @PostMapping("/saveOrUpdate")
    @ApiOperation(value = "新增/更新")
    @LogAnnotation(module = "system", recordRequestParam = true)
    public Result saveOrUpdate(@RequestBody SysDevice sysDevice) {
        if (StringUtils.isBlank(sysDevice.getName())) {
            logger.error("设备名称为空！");
            throw new IllegalArgumentException("设备名称为空！");
        }
        boolean b = sysDeviceService.saveOrUpdateDevice(sysDevice);
        return Result.result(b);
    }

    @GetMapping("/getDeviceAll")
    @ApiOperation(value = "获取所有Device")
    @LogAnnotation(module = "system", recordRequestParam = false)
    public Result getDeviceAll() {
        return Result.succeed(sysDeviceService.list());
    }

    @GetMapping("/getDeviceAndStatus")
    @ApiOperation(value = "获取所有Device")
    @LogAnnotation(module = "system", recordRequestParam = false)
    public Result getDeviceAndStatus() throws Exception {
        //获取当前人所拥有的设备，如果没有就获取当前人所拥有的机构的持有的设备
        List<SysDevice> dbDevices = null;//sysDeviceService.list();
        Authentication authentication = AuthenticationUtil.getAuthentication();
        if (CollectionUtils.isEmpty(authentication.getSysDevices())) {
            List<SysOrgan> organByUserId = userService.getOrganByUserId(authentication.getId());
            dbDevices = new ArrayList<>();
            if (!CollectionUtils.isEmpty(organByUserId)) {
                Set<String> organIds = organByUserId.stream().map(organ -> organ.getId()).collect(Collectors.toSet());
                List<SysOrgan> sysOrganByIds = sysOrganService.getSysOrganByIds(organIds);
                if (!CollectionUtils.isEmpty(sysOrganByIds)) {
                    for (SysOrgan sysOrganById : sysOrganByIds) {
                        dbDevices.addAll(sysOrganById.getSysDevices());
                    }
                }
            }

        } else {
            dbDevices = authentication.getSysDevices();
        }
        //获取所有在线设备
        Map<String, List<SysDevice>> deviceMap = new HashMap<>();
        AuthenticationUtil.getOnLineUser().forEach(u -> {
            List<SysDevice> sysDevices = u.getSysDevices();
            sysDevices.forEach(d -> {
                d.setToken(u.getToken());
                d.setName(d.getName() + "(" + u.getNickName() + ")");
            });
            Map<String, List<SysDevice>> onLineDevivceMap = sysDevices.stream().collect(Collectors.groupingBy(SysDevice::getId));
            if (!CollectionUtils.isEmpty(onLineDevivceMap)) {
                onLineDevivceMap.forEach((key, value) -> {
                    List<SysDevice> sysDevices1 = deviceMap.get(key);
                    if (CollectionUtils.isEmpty(sysDevices1)) {
                        sysDevices1 = new ArrayList<>();
                        deviceMap.put(key, sysDevices1);
                    }
                    sysDevices1.addAll(value);
                });
            }
        });
        //标注当前所持有的设备在线状态
        dbDevices.forEach(device -> {
            List<SysDevice> sysDevices = deviceMap.get(device.getId());
            if (CollectionUtils.isEmpty(sysDevices)) {
                device.setToken("");
            } else {
                for (int i = 0; i < sysDevices.size(); i++) {
                    SysDevice d = sysDevices.get(i);
                    if (d.getId().equals(device.getId()) && d.isOnLine()) {
                        device.setOnLine(d.isOnLine());
                        device.setToken(d.getToken());
                        break;
                    }
                }
            }

        });
        return Result.succeed(dbDevices);
    }

    @GetMapping("/getDeviceByOrganId/{organId}")
    @ApiOperation(value = "根据机构id获取所有Device")
    @LogAnnotation(module = "system", recordRequestParam = false)
    public Result getDeviceByOrganId(@PathVariable String organId) {
        return Result.succeed(sysDeviceService.findDeviceByOrganId(organId));
    }

    @PostMapping("/getDeviceByOrganIds")
    @ApiOperation(value = "根据机构id获取所有Device")
    @LogAnnotation(module = "system", recordRequestParam = false)
    public Result getDeviceByOrganIds(@RequestBody List<String> organIds) {
        return Result.succeed(sysDeviceService.findDeviceByOrganIds(organIds));
    }

    @GetMapping("/deviceToOnLine/{sn}")
    @ApiOperation(value = "设备在线")
    @LogAnnotation(module = "system", recordRequestParam = false)
    public Result deviceToOnLine(@PathVariable String sn) {
        return setDeviceStatus(sn, true);
    }

    @GetMapping("/deviceToOffLine/{sn}")
    @ApiOperation(value = "设备离线")
    @LogAnnotation(module = "system", recordRequestParam = false)
    public Result deviceToOffLine(@PathVariable String sn) {
        return setDeviceStatus(sn, false);
    }

    /**
     * 设备在的在离线状态
     *
     * @param sn
     * @param b
     * @return
     */
    private Result setDeviceStatus(String sn, boolean b) {
        if (StringUtils.isBlank(sn)) {
            logger.error("设备编码为空！");
            throw new IllegalArgumentException("设备编码为空！");
        }
        Authentication authentication = AuthenticationUtil.getAuthentication();
        List<SysDevice> sysDevices = authentication.getSysDevices();
        for (int i = 0; i < sysDevices.size(); i++) {
            SysDevice device = sysDevices.get(i);
            if (sn.equals(device.getCode())) {
                device.setOnLine(b);
                BroadcastMessageUtil.asyncbroadcastDeviceStatus(device);
                AuthenticationUtil.setAuthenticationToRedis(authentication);
                return Result.succeed(device);
            }
        }
        return Result.failed("设备状态更新失败，原因：未能找到设备！");
    }
}
